#include <jni.h>
#include <string>
#include <android/log.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <sys/select.h>
#include "include/gpiod.h"

// Write C++ code here.
//
// Do not forget to dynamically load the C++ library into your application.
//
// For instance,
//
// In MainActivity.java:
//    static {
//       System.loadLibrary("myapplication");
//    }
//
// Or, in MainActivity.kt:
//    companion object {
//      init {
//         System.loadLibrary("myapplication")
//      }
//    }

const char 		    	*chipname   = "gpiochip0";	//GPIO1
struct 	gpiod_chip 	*chip;
unsigned int		line_num ;
struct 	gpiod_line 	*line18,*line20,*line22 ;
//unsigned int 		line_num_18 = 18;  		// 偏移GPIO 18	GPIO1_18
//unsigned int 		line_num_20 = 20;  		// 偏移GPIO 20	GPIO1_20
//unsigned int 		line_num_22 = 22;  		// 偏移GPIO 20	GPIO1_20
int 		    	ret;
bool		    	isused;
const char	    	*chip_name;
int                 count18 = 0;
int                 count20 = 0;
int                 count22 = 0;

//设置0/1，控制led亮灭 gpio18
int set_led_value_18(int which,int status)
{

    __android_log_print(ANDROID_LOG_DEBUG, "函数：set_led_value", "开始设置0/1控制亮灭:%d",status);


    //4、获取GPIO18引脚句柄
    line18 = gpiod_chip_get_line(chip,which);
    if ( !line18 )
    {
        __android_log_print(ANDROID_LOG_DEBUG, "gpiod_chip_get_line", "Get line failed. line_num: %u",which);

        return 0;
    }

    if (count18 == 0)
    {

        //5、判断GPIO18是否被占用
        isused = gpiod_line_is_used(line18);
        if (isused)
        {
            // GPIO线正在被使用
            __android_log_print(ANDROID_LOG_DEBUG, "GPIO18 isused", "GPIO18线正在被使用");
            return 0;
        }
        else
        {
            // GPIO线没有被使用
            __android_log_print(ANDROID_LOG_DEBUG, "GPIO18 is not used", "GPIO18线没有被使用");
        }

        //6、设置GPIO18为输出模式
        ret = gpiod_line_request_output(line18,NULL ,1);
        if (ret < 0) {
            __android_log_print(ANDROID_LOG_DEBUG, "设置为输出模式", "输出模式设置失败");

            return 0;
        }
        __android_log_print(ANDROID_LOG_DEBUG, "设置为输出模式", "输出模式设置成功！");

        count18 = 1;
    }

    //设置GPIO18的值
    ret = gpiod_line_set_value(line18, status);//设置输出状态
    if (ret < 0) {
        __android_log_print(ANDROID_LOG_DEBUG, "Set On/Off", "Set line output failed. val:%d!",status);

        return 0;
    }

    ret = gpiod_line_get_value(line18);
    __android_log_print(ANDROID_LOG_DEBUG, "GPIO18的值", "GPIO18的值为:%d!",ret);

    if (ret == 0)
    {
        __android_log_print(ANDROID_LOG_DEBUG, "--LED状态--", "状态为：--打开!--");
    }
    else
    {
        {
            __android_log_print(ANDROID_LOG_DEBUG, "--LED状态--", "状态为：--关闭!--");
        }
    }

    return 0;
}

//设置0/1，控制led亮灭   gpio20
int set_led_value_20(int which,int status)
{

    __android_log_print(ANDROID_LOG_DEBUG, "函数：set_led_value", "开始设置0/1控制亮灭:%d",status);


    //4、获取GPIO20引脚句柄
    line20 = gpiod_chip_get_line(chip,which);
    if ( !line20 )
    {
        __android_log_print(ANDROID_LOG_DEBUG, "gpiod_chip_get_line", "Get line failed. line_num: %u",which);

        return 0;
    }

    if (count20 == 0)
    {

        //5、判断GPIO20是否被占用
        isused = gpiod_line_is_used(line20);
        if (isused)
        {
            // GPIO线正在被使用
            __android_log_print(ANDROID_LOG_DEBUG, "GPIO18 isused", "GPIO20线正在被使用");
            return 0;
        }
        else
        {
            // GPIO线没有被使用
            __android_log_print(ANDROID_LOG_DEBUG, "GPIO18 is not used", "GPIO20线没有被使用");
        }

        //6、设置GPIO18为输出模式
        ret = gpiod_line_request_output(line20,NULL ,1);
        if (ret < 0) {
            __android_log_print(ANDROID_LOG_DEBUG, "设置为输出模式", "输出模式设置失败");

            return 0;
        }
        __android_log_print(ANDROID_LOG_DEBUG, "设置为输出模式", "输出模式设置成功！");

        count20 = 1;
    }

    //设置GPIO18的值
    ret = gpiod_line_set_value(line20, status);//设置输出状态
    if (ret < 0) {
        __android_log_print(ANDROID_LOG_DEBUG, "Set On/Off", "Set line output failed. val:%d!",status);

        return 0;
    }

    ret = gpiod_line_get_value(line20);
    __android_log_print(ANDROID_LOG_DEBUG, "GPIO20的值", "GPIO20的值为:%d!",ret);

    if (ret == 0)
    {
        __android_log_print(ANDROID_LOG_DEBUG, "--LED状态--", "状态为：--打开!--");
    }
    else
    {
        {
            __android_log_print(ANDROID_LOG_DEBUG, "--LED状态--", "状态为：--关闭!--");
        }
    }

    return 0;
}


//设置0/1，控制led亮灭   gpio20
int set_led_value_22(int which,int status)
{

    __android_log_print(ANDROID_LOG_DEBUG, "函数：set_led_value", "开始设置0/1控制亮灭:%d",status);


    //4、获取GPIO22引脚句柄
    line22 = gpiod_chip_get_line(chip,which);
    if ( !line22 )
    {
        __android_log_print(ANDROID_LOG_DEBUG, "gpiod_chip_get_line", "Get line failed. line_num: %u",which);

        return 0;
    }

    if (count22 == 0)
    {

        //5、判断GPIO22是否被占用
        isused = gpiod_line_is_used(line22);
        if (isused)
        {
            // GPIO线正在被使用
            __android_log_print(ANDROID_LOG_DEBUG, "GPIO18 isused", "GPIO22线正在被使用");
            return 0;
        }
        else
        {
            // GPIO线没有被使用
            __android_log_print(ANDROID_LOG_DEBUG, "GPIO18 is not used", "GPIO22线没有被使用");
        }

        //6、设置GPIO22为输出模式
        ret = gpiod_line_request_output(line22,NULL ,1);
        if (ret < 0) {
            __android_log_print(ANDROID_LOG_DEBUG, "设置为输出模式", "输出模式设置失败");

            return 0;
        }
        __android_log_print(ANDROID_LOG_DEBUG, "设置为输出模式", "输出模式设置成功！");

        count22 = 1;
    }

    //设置GPIO22的值
    ret = gpiod_line_set_value(line22, status);//设置输出状态
    if (ret < 0) {
        __android_log_print(ANDROID_LOG_DEBUG, "Set On/Off", "Set line output failed. val:%d!",status);

        return 0;
    }

    ret = gpiod_line_get_value(line22);
    __android_log_print(ANDROID_LOG_DEBUG, "GPIO22的值", "GPIO22的值为:%d!",ret);

    if (ret == 0)
    {
        __android_log_print(ANDROID_LOG_DEBUG, "--LED状态--", "状态为：--打开!--");
    }
    else
    {
        {
            __android_log_print(ANDROID_LOG_DEBUG, "--LED状态--", "状态为：--关闭!--");
        }
    }

    return 0;
}


extern "C"
JNIEXPORT jint JNICALL
Java_com_example_myapplication_HardControl_ledOpen(JNIEnv *env, jclass clazz) {

    // TODO: implement ledOpen()
//    __android_log_print(ANDROID_LOG_DEBUG, "LEDDemo", "------native ledOpen-------");


    //1、OPEN：打开chipgpio0
    chip = gpiod_chip_open_by_name(chipname);

    if (!chip) {
        __android_log_print(ANDROID_LOG_INFO, "Open chipgpio0", "Open chip by name failed. name: %s\n", chipname);

        return 0;
    }
    __android_log_print(ANDROID_LOG_DEBUG, "Open chipgpio0", "Successfully opened chip:%s",chipname);

    //2、获取打开的设备名
    chip_name = gpiod_chip_name(chip);
    __android_log_print(ANDROID_LOG_DEBUG, "gpiod_chip_name", "The GPIO chip name as represented in the kernel: %s",chip_name);

    //3、获取打开的chipgpio0的引脚个数
    line_num = gpiod_chip_num_lines(chip);
    __android_log_print(ANDROID_LOG_DEBUG, "gpiod_chip_num_lines", "Line number:%u",line_num);




    return 0;
}


extern "C"
JNIEXPORT jint JNICALL
Java_com_example_myapplication_HardControl_ledCtrl_1on(JNIEnv *env, jclass clazz, jint which,
                                                       jint status) {
    // TODO: implement ledCtrl_on()

    __android_log_print(ANDROID_LOG_DEBUG, "ledCtrl_on", "status 值：%d",status);

    switch (which) {
        case 18:
            set_led_value_18(which,status);
            break;
        case 20:
            set_led_value_20(which,status);
            break;
        case 22:
            set_led_value_22(which,status);
            break;

    }


    return 0;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_example_myapplication_HardControl_ledCtrl_1off(JNIEnv *env, jclass clazz, jint which,
                                                        jint status) {
    // TODO: implement ledCtrl_off()

    __android_log_print(ANDROID_LOG_DEBUG, "ledCtrl_off", "status 值：%d",status);

    switch (which) {
        case 18:
            set_led_value_18(which,status);
            break;
        case 20:
            set_led_value_20(which,status);
            break;
        case 22:
            set_led_value_22(which,status);
            break;

    }

    return 0;
}


extern "C"
JNIEXPORT jint JNICALL
Java_com_example_myapplication_HardControl_ledCtrl_1close(JNIEnv *env, jclass clazz,jint which) {
    // TODO: implement ledCtrl_close()

    set_led_value_18(which,1);
    gpiod_line_release(line18);

    set_led_value_20(which,1);
    gpiod_line_release(line20);

    set_led_value_22(which,1);
    gpiod_line_release(line22);

    gpiod_chip_close(chip);

    return 0;

}